import axios from "axios";
import Cache from "./cache";
import State from './state';
import Util from "./util";
import Bridge from "./bridge";
import { Message } from "element-ui";
import { NOTICE_CODE, APP_FUN, APP_LISTENER } from "./enums";
import Config from "../config"
import md5 from 'js-md5';
import Router from '../router'

axios.defaults.withCredentials = true; // 允许 cors 请求带 cookie
axios.defaults.timeout = 3e4;

const toast = (message) => {
  Message({
    message,
    type: 'error'
  });
};
/**
 * ⚠️ 固定参数
 * @param {默认} config
 */
const setHeader = (config) => {
  let header = Cache.user.get();
  if (header) config.headers["cp_profile_id"] = header["cp_profile_id"];
  // for (let k in temp) {
  //     if (temp[k]) config.headers[k] = temp[k];
  // }
};
/**
 * ⚠️ 跨域传参
 * @param {默认} config
 */
const setAuthorization = (config) => {
  let loginInfo = State['LOGIN_INFO'];
  if (loginInfo) {
    config.headers["satoken"] = loginInfo.tokenValue
  }
};

/**
   * 生成16位 uuid 字符串
   * @returns 
   */
const generateUUID = () => {
  let d = new Date().getTime();
  if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
    d += performance.now();
  }
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    let r = (d + Math.random() * 16) % 16 | 0;
    d = Math.floor(d / 16);
    return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
  });
}
/**
 * 对象字段按 A-Za-z 排序，并返回 key=value&... 格式字符串
 * @param {*} obj 
 * @returns 
 */
const sortObjectKeys = obj => {
  let sortedKeys = Object.keys(obj).sort(function (a, b) {
    return a.toLowerCase().localeCompare(b.toLowerCase());
  });
  let sortedKeyValuePairs = sortedKeys.map(function (key) {
    return key + '=' + obj[key];
  });
  return sortedKeyValuePairs.join('&');
}
/**
 * 获取加密参数
 * @param {*} params 
 * @returns 
 */
const getSign = params => {
  let s1 = sortObjectKeys(params);
  let s2 = md5(s1.toLocaleUpperCase()) + Config.salt
  return md5(s2).toLocaleUpperCase()
}
/**
 * 配置全量固定参数
 * @param {*} config 
 */
const setStandParams = (config) => {
  let standParams = Config.params
  let { method, data = {} } = config
  if (method == 'post') {
    const allParams = Object.assign(standParams, { data }, {
      clientTime: +new Date,
      nonce: generateUUID(),
    })
    if (State['LOGIN_INFO']) {
      let { tokenValue: token, userId } = State['LOGIN_INFO']
      Object.assign(allParams, {
        token,
        userId,
      })
    } else {
      delete allParams.token
      delete allParams.userId
    }
    config.data = {
      ...allParams,
      sign: getSign(allParams)
    }
  }
}

const reLogin = (message) => {
  toast(message);
  State['USER_INFO'] = null
  State['LOGIN_INFO'] = null
  Router.replace({
    name: 'Login'
  })
};

axios.interceptors.request.use(
  (config) => {
    config.headers["Content-Type"] = "application/json;charset=UTF-8";
    // setHeader(config);
    setAuthorization(config);
    setStandParams(config)

    return config;
  },
  (error) => Promise.reject(error)
);

axios.interceptors.response.use(
  (res) => {
    let { status, resultCode: code, resultMsg: message, msg } = res.data;
    if (code == 200 || status == 200) {
      return res.data;
    } else if (code == 5107) {
      reLogin(message)
    } else {
      try {
        let errInfo = res.data.debug.exception;
        if (
          errInfo.includes("Request method") &&
          errInfo.includes("not supported")
        )
          toast(NOTICE_CODE[405]);
        toast(errInfo)
        log(2, errInfo);
      } catch (error) {
        toast(message)
        log(1, message || msg);
      }
      return res.data;
    }
  },
  (err) => {
    let { message, response } = err;
    let text = "";
    if (response && response.status) {
      text = response.status >= 500 ? NOTICE_CODE[500] : NOTICE_CODE[httpCode];
    } else {
      if (message === "Network Error") {
        // 大部分异常会走这里，上层没有抛出具体的错误分析，如跨域等
        text = NOTICE_CODE[1003];
        Bridge._js2(APP_FUN[5001]);
        Bridge._2js(APP_LISTENER[5001], (status) => {
          if (status == 3) {
            text = NOTICE_CODE[1001];
            toast(text);
          }
        });
      } else if (message.includes("timeout")) {
        text = NOTICE_CODE[1002];
      } else {
        text = NOTICE_CODE[1003];
      }
    }
    toast(text);

    throw new Error(text);
  }
);
export default {
  get: (url, params) => {
    return new Promise((resolve, reject) => {
      axios
        .get(url, {
          params,
        })
        .then((res) => {
          res && resolve(res);
        })
        .catch((err) => {
          reject(err);
        });
    });
  },
  post: (url, data) => {
    return new Promise((resolve, reject) => {
      axios
        .post(url, {
          ...data,
        })
        .then((res) => {
          res && resolve(res);
        })
        .catch((err) => {
          reject(err);
        });
    });
  },
};
